package com.songshuai.webapi.baseapi.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * oss上传工具
 * @Author: lhx
 * @Date: 2018/11/23 16:07
 * @Version 1.0
 */
@Slf4j
public class OssUploadUtil {

    private OSSClient ossClient;

    private String buckteName;

    private String endpoint;

    private String accessKeyId;

    private String accessKeySecret;

    private static final int FILE_EXPIRATION = 87600;

    private OssUploadUtil(String buckteName, String endpoint, String accessKeyId, String accessKeySecret){
        this.buckteName = buckteName;
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        this.endpoint=endpoint;
        this.accessKeyId=accessKeyId;
        this.accessKeySecret=accessKeySecret;
    }

    /**
     * 初始化对象
     * @param buckteName
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @return
     */
    public static OssUploadUtil build(String buckteName, String endpoint, String accessKeyId, String accessKeySecret) {
        return new OssUploadUtil(buckteName, endpoint, accessKeyId, accessKeySecret);
    }


    /**
     * 文件上传
     *
     * @param file
     *            文件
     * @param key
     *            OOS文件key
     * @return boolean
     */
    public boolean upload(File file, String key) {
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        boolean temp = false;
        try {
            PutObjectResult result = ossClient.putObject(buckteName, key, file);
            temp = StringUtils.isNotBlank(result.getRequestId());
        } catch (Exception e) {
            log.error("file upload is error",e);
        } finally {
            ossClient.shutdown();
        }
        return temp;
    }

    /**
     * 文件流上传
     *
     * @param inputStream
     *            文件流
     * @param key
     *            OOS文件key  路径/文件名
     * @return boolean
     */
    public boolean upload(InputStream inputStream, String key) {
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        boolean temp = false;
        try {
            if (StringUtils.isNotBlank(key)){
                PutObjectResult result = ossClient.putObject(buckteName, key, inputStream);
                temp = StringUtils.isNotBlank(result.getRequestId());
            }
        } catch (Exception e) {
            log.error("inputStream file upload is error",e);
        } finally {
            ossClient.shutdown();
        }
        return temp;
    }




    /**
     * 获取OOS文件url，有读取有效期
     *
     * @param key
     *            OOS文件key
     * @param amount
     *            有效时长，单位：小时
     */
    public String getOSSUrl(String key, int amount) {
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        String urlStr = "";
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.HOUR, amount);
            Date date = calendar.getTime();

            URL url = ossClient.generatePresignedUrl(buckteName, key, date);
            urlStr = url.toString();
            urlStr.replaceAll("%2F", "/");
        } catch (Exception e) {
            log.error("get ossurl is error",e);
        } finally {
            ossClient.shutdown();
        }
        return urlStr;
    }


    /**
     * 获取OOS文件url，读取有效期为10年
     *
     * @param key
     *            OOS文件key
     * @return
     */
    public String getOSSTenYearUrl(String key) {
        return getOSSUrl(key, FILE_EXPIRATION);
    }




    /**
     * 删除阿里云服务器上的文件
     *
     * @param key
     *            OOS文件key
     * @return
     */
    public String deleteByKey(String key) {
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        try {
            // 判断服务器文件是否存在
            boolean found = ossClient.doesObjectExist(buckteName, key);
            if (found) {
                // 删除服务器文件
                ossClient.deleteObject(buckteName, key);
                return "删除成功！";
            } else {
                return "文件不存在！";
            }
        } catch (Exception e) {
            log.error("get ossurl is error",e);
        } finally {
            ossClient.shutdown();
        }
        return "删除失败！";
    }

    /**
     * 批量删除阿里云服务器上的文件
     *
     * @param keys
     *            OOS文件keys
     * @return
     */
    public String deleteByKeys(List<String> keys) {
        if (keys.size() > 1000) {
            return "删除数据过多！";
        }
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        try {
            DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(buckteName);
            deleteObjectsRequest.setKeys(keys);
            ossClient.deleteObjects(deleteObjectsRequest);
            return "删除成功！";
        } catch (Exception e) {
            log.error("delete keys is error",e);
        } finally {
            ossClient.shutdown();
        }
        return "删除失败！";
    }

    /**
     * 获取OSS文件列表
     *
     * @param keyPrefix
     *            文件夹前缀
     * @return objects-文件列表（key-OSS文件key，value-文件上传时间 <br>
     *         num-当前文件夹下有多少文件 <br>
     *         size-当前文件夹的大小（单位：byte）
     */
    public Map<String, Object> getObjects(String keyPrefix) {
        this.ossClient = new OSSClient(endpoint, accessKeyId,accessKeySecret);
        Map<String, Object> result = null;
        try {
            List<Map<String, Date>> objects = new ArrayList<>();
            ObjectListing objectListing;
            final int maxKeys = 1000;
            String nextMarker = null;
            int num = 0;
            long size = 0l;
            do {
                objectListing = ossClient.listObjects(new ListObjectsRequest(buckteName)
                        .withPrefix(keyPrefix).withMarker(nextMarker).withMaxKeys(maxKeys));
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                Map<String, Date> map = new HashMap<>();
                for (OSSObjectSummary s : sums) {
                    map.put(s.getKey(), s.getLastModified());
                    size += s.getSize();
                    num++;
                }
                objects.add(map);
                nextMarker = objectListing.getNextMarker();
            } while (objectListing.isTruncated());
            result = new HashMap<>();
            result.put("objects", objects);
            result.put("num", num);
            result.put("size", size);
            return result;
        } catch (Exception e) {
            log.error("get objects is error",e);
        } finally {
            ossClient.shutdown();
        }
        return result;
    }



}
